package org.lvxiao.example.redis;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * redis 配置类   
 * RedisConnectionFactory、RedisTemplate会自动装配
 * @see {@link org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration}
 * @author 吕潇
 */
@Configuration
public class RedisConfig {

	/**
	 * 创建redisTemplate
	 * 所有序列化k/v都会默认使用{@link org.springframework.data.redis.serializer.JdkSerializationRedisSerializer}
	 * 默认的序列化类用使用byte数组进行存储， 在使用redis可视化客户端看到都是乱码不直观
	 * 使用StringRedisSerializer序列化Key，  Jackson2JsonRedisSerializer序列化值， 可以观察到对象结构层次
	 * @param redisConnectionFactory  
	 * 		配置 spring.redis.* 会自动注入
	 * 		默认使用: {@link org.springframework.data.redis.connection.jedis.JedisConnectionFactory}
	 * @return
	 */
	@Bean
	public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
		Jackson2JsonRedisSerializer<Object> valueSerializer = jackson2JsonRedisSerializer();
		StringRedisSerializer keySerializer = new StringRedisSerializer();
		RedisTemplate<?, ?> redisTemplate = new RedisTemplate<>();
		redisTemplate.setConnectionFactory(redisConnectionFactory);
		redisTemplate.setKeySerializer(keySerializer);
		redisTemplate.setValueSerializer(valueSerializer);
		redisTemplate.setHashKeySerializer(keySerializer);
		redisTemplate.setHashValueSerializer(valueSerializer);
		return redisTemplate;
	}
	
	/**
	 * 定义序列化类
	 * @return
	 */
	public Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
		Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
		ObjectMapper objectMapper = new ObjectMapper();
		objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
		return jackson2JsonRedisSerializer;
	}
	
}
